package cn.zyq.charging.device.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.io.Serializable;
import java.util.Map;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.geo.*;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;
import cn.zyq.charging.device.service.StationService;
import cn.zyq.charging.common.pojo.vo.StationInfoVO;
import cn.zyq.charging.device.constant.DeviceCacheKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisGeoCommands;

@Slf4j
@Service
public class StationServiceImpl implements StationService {

    @Autowired
    private RedisTemplate<String, Serializable> redisTemplate;

    /**
     * 获取附近的充电站列表
     * @param longitude 经度  浪  dʒɪ   t  u   的
     * @param latitude 纬度  赖 忒 t  u   的
     * @param radius 半径/距离
     * @return 充电站列表
     */
    public List<StationInfoVO> getNearStations(Double longitude, Double latitude, Double radius) {
        //1.获取操作redis不同类型的对象(BoundGeoOperations,ValueOperations,HashOperations)
        //根据指定的key，利用redisTemplate的boundGeoOps()方法获取BoundGeoOperations对象(用来操作GEO数据)
        BoundGeoOperations<String, Serializable> stations= redisTemplate.boundGeoOps(DeviceCacheKey.STATION_LOCATION_KEY);
        //GeoOperations stations2= redisTemplate.opsForGeo(); 不用这个(用上边的boundGeoOps方法)
        //根据redisTemplate的opsForValue()方法获取ValueOperations对象(用来操作String数据)
        ValueOperations<String, Serializable> valueOperations=redisTemplate.opsForValue();
        //根据redisTemplate的opsForHash()方法获取HashOperations对象(用来操作hash数据)
        HashOperations<String,Object,Object> hashOperations=redisTemplate.opsForHash();
        //2.
        // 通过用户的经纬度创建RedisGEO的Point 用户的位置 (点对象Point)
        Point point=new Point(longitude,latitude);//构建圆心对象
        //通过用户传入的查找距离(半径),构建Distance对象  //单位是：千米
        Distance distance=new Distance(radius, Metrics.KILOMETERS);//构建半径对象
        //使用圆心和半径，构建圆对象
        Circle circle=new Circle(point,distance);//(使用圆心，半径)构建圆对象
        //3.设置查询参数
        RedisGeoCommands.GeoRadiusCommandArgs args= RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
        //设置参数 告诉Redis查询的时候返回距离
        args.includeDistance();
        //设置参数 告诉Redis查询的时候返回经纬度
        args.includeCoordinates();
        //4.根据circle和args查询参数，调用radius()方法查询 附近的充电站GEO位置信息// 调用的是 Redis GEORADIUS 这个命令
        GeoResults<RedisGeoCommands.GeoLocation<Serializable>> geoResults=stations.radius(circle, args);
        log.debug("通过经度:{},维度:{},距离:{} 查询附近的充电站:{}",longitude,latitude,radius,geoResults);
        List<StationInfoVO> stationInfoVOS=new ArrayList();
        for(GeoResult<RedisGeoCommands.GeoLocation<Serializable>> geoResult:geoResults){
            //站点的id
            //content里的name属性是之前StationDataInit缓存预热保存pointMap的key(站点id)，value是 point
            Serializable stationId=geoResult.getContent().getName();
            //获取充电站和入参位置经纬度 的距离
            double stationDistance=geoResult.getDistance().getValue();
            //获取充电站的位置 经纬度
            Point stationPoint=geoResult.getContent().getPoint();
            //通过 保存为Redis String类型获取场站信息
            String stationInfoHashBigKey=DeviceCacheKey.STATION_DETAIL_STRING_KEY+stationId;
            String stationInfoHashSmallKey = "name";
            //从redis中获取hash类型的数据
            Object object=hashOperations.get(stationInfoHashBigKey,stationInfoHashSmallKey);
            log.debug("通过大key:{},小key:{},获取小map里具体的 name 的值 {},只能获取一个",stationInfoHashBigKey,stationInfoHashSmallKey,object);
            //entries redis 命令 HGETALL 推荐用一次命令全部获取(hGetAll)
            //通过大key,获取小map所有值
            Map<Object, Object> entries=hashOperations.entries(stationInfoHashBigKey);
            log.debug("通过大key:{},获取小map所有值 {},全部获取,推荐使用",stationInfoHashBigKey,entries);
        }
        return null;
    }

    public StationInfoVO getStationDetail(Integer id) {
        return null;
    }
}
